// GraphPane.cpp : implementation file
//

#include "stdafx.h"
#include "WebGUI.h"
#include "GraphPane.h"


// CGraphPane

IMPLEMENT_DYNAMIC(CGraphPane, CDockablePane)

CGraphPane::CGraphPane()
{

	m_nDataIndex = 0 ;
}

CGraphPane::~CGraphPane()
{
}


BEGIN_MESSAGE_MAP(CGraphPane, CDockablePane)
	ON_WM_PAINT()
	ON_WM_SETFOCUS()
	ON_WM_SIZE()
	ON_WM_CREATE()
	ON_WM_DESTROY()
END_MESSAGE_MAP()

void CGraphPane::OnPaint()
{
	CPaintDC dc(this); // device context for painting


	// using double buffering to avoid flicker in real-time drawing
	
	CDC memDC ;
	CBitmap bmp ;

	CRect rcClient ;
	GetClientRect(rcClient);

	memDC.CreateCompatibleDC(&dc);
	bmp.CreateCompatibleBitmap(&dc,rcClient.Width(),rcClient.Height()) ;
	memDC.SelectObject(&bmp);

	// DrawBackground
	DrawBK(&memDC);
	
	// Draw Plots
	DrawPlots(&memDC);

	// copy graphic buffer to the screen's buffer
	dc.BitBlt(0,0,rcClient.Width(),rcClient.Height(),&memDC, 0,0, SRCCOPY) ;

	memDC.DeleteDC();
	bmp.DeleteObject() ;

}

void CGraphPane::OnSetFocus(CWnd* pOldWnd)
{
	CDockablePane::OnSetFocus(pOldWnd);

}

void CGraphPane::OnSize(UINT nType, int cx, int cy)
{
	CDockablePane::OnSize(nType, cx, cy);

	if (CanAdjustLayout())
	{
		CRect rc;
		GetClientRect(rc);
		Invalidate(FALSE);
	}
}

int CGraphPane::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CDockablePane::OnCreate(lpCreateStruct) == -1)
		return -1;

	return 0;
}


void CGraphPane::OnDestroy()
{
	CDockablePane::OnDestroy();
}


CPoint CGraphPane::ToDrawCoordinate(CRect r, float fX,float fY) 
{
	float fCx = ((float)r.Width()-200-50.0f)/100  ;
	float fCy = ((float)r.Height()-70.0f)/100  ;
	CPoint pt ;
	pt.x =  50 + fX*fCx ;
	pt.y = r.bottom - 50 - fY*fCy ;
	return pt ;
}
void CGraphPane::DrawBK(CDC *pDC)
{

	CRect rcClient ;
	GetClientRect(rcClient);

	int nWidth ;
	int nheight ;

	// cliping to avoid drawing outside the drawing area
	CRgn rgn ;
	rgn.CreateRectRgnIndirect(&rcClient);
	pDC->SelectClipRgn(&rgn,RGN_COPY);
	nWidth = rcClient.Width() ;
	nheight = rcClient.Height() ;


	COLORREF clrBack = 0xe0ffff;
	COLORREF clrAxis = RGB(0,0,0);
	COLORREF clrGrid = RGB(200,200,200);

	CPen penAxis( PS_SOLID,  1, clrAxis ) ;
	CPen penGrid( PS_DOT,  1, clrGrid) ;


	CBrush brBack( clrBack ) ;

	pDC->FillRect( &rcClient, &brBack ) ;

	CFont font ;
	font.CreatePointFont(100, "Arial");
	CFont *pOldFont = (CFont*)pDC->SelectObject(&font);

	pDC->SetBkMode(TRANSPARENT);
	pDC->SelectObject(&penGrid);
	
	// drawing dot lines 
	for ( int n=0 ; n <= 100 ;n+=20)
	{
		CPoint p1 = ToDrawCoordinate(rcClient,n,0) ;
		CPoint p2 = ToDrawCoordinate(rcClient,n,100) ;
		pDC->MoveTo(p1);
		pDC->LineTo(p2);

		p1 = ToDrawCoordinate(rcClient,0,n) ;
		p2 = ToDrawCoordinate(rcClient,100,n) ;
		pDC->MoveTo(p1);
		pDC->LineTo(p2);


		p1.x = 0 ;
		p1.y -=5 ;

		CString str ;
		str.Format("%d%%", n);
		pDC->TextOut(p1.x,p1.y, str);


	}
	
	// drawing Axis
	pDC->SelectObject(&penAxis);
	CPoint p1 = ToDrawCoordinate(rcClient,0,0) ;
	CPoint p2 = ToDrawCoordinate(rcClient,100,0) ;
	pDC->MoveTo(p1);
	pDC->LineTo(p2);
	p1 = ToDrawCoordinate(rcClient,0,0) ;
	p2 = ToDrawCoordinate(rcClient,0,100) ;
	pDC->MoveTo(p1);
	pDC->LineTo(p2);


}

void CGraphPane::DrawPlots(CDC *pDC)
{
	CRect rcClient ;
	GetClientRect(rcClient);
	for (int n=0;n<m_aNodes.GetCount();n++)
	{
		COLORREF clrPlot = m_aNodes[n].clr ;
		CPen penPlot( PS_SOLID,  2, clrPlot ) ;
		pDC->SelectObject(&penPlot);

		for (int m=1;m<DRAW_BUFF_LEN;m++)
		{
			if (m_aNodes[n].afCPU[m]>=0 && m_aNodes[n].afCPU[m-1]>=0)
			{
				CPoint p1 = ToDrawCoordinate(rcClient, m-1,m_aNodes[n].afCPU[m-1] );
				CPoint p2 = ToDrawCoordinate(rcClient, m,m_aNodes[n].afCPU[m] );
				pDC->MoveTo(p1);
				pDC->LineTo(p2);
			}
		}

		CPoint p1 = ToDrawCoordinate(rcClient, 101,100-10*n );
		pDC->TextOut(p1.x,p1.y,m_aNodes[n].strNodeIP);

		CRect r ( rcClient.Width()-70,p1.y,rcClient.Width()-20,p1.y+10) ;
		CBrush br(m_aNodes[n].clr ) ;
		pDC->SelectObject(&br);
		pDC->Rectangle(&r);
	}

	if (m_nDataIndex>0)
	{
		COLORREF clrPlot2 = RGB(0,0,0);
		CPen penPlot2( PS_SOLID,  1, clrPlot2 ) ;
		pDC->SelectObject(&penPlot2);
		CPoint p1 = ToDrawCoordinate(rcClient, m_nDataIndex-1,0 );
		CPoint p2 = ToDrawCoordinate(rcClient, m_nDataIndex-1,100 );
		pDC->MoveTo(p1);
		pDC->LineTo(p2);
	}


}

void CGraphPane::UpdateList( CArray<SERVER_NODE,SERVER_NODE> &aNodes )
{

	//delete those plots that doesnt exit anymore
	for (int n=0;n<m_aNodes.GetCount();n++)
	{

		BOOL bFound = FALSE ;
		for (int m=0;m<aNodes.GetCount();m++)
		{
			if (m_aNodes[n].strNodeIP == aNodes[m].strIP)
			{
				bFound=TRUE ;
			}
		}
		if (!bFound)
		{
			m_aNodes.RemoveAt(n);
		}
	}

	// add data to current nodes or create new node if it deosnt exist
	for (int n=0;n<aNodes.GetCount();n++)
	{
		BOOL bFound = FALSE ;
		for (int m=0;m<m_aNodes.GetCount();m++)
		{
			if (m_aNodes[m].strNodeIP == aNodes[n].strIP)
			{

				m_aNodes[m].nStart = min( m_aNodes[m].nStart , m_nDataIndex ) ;
				m_aNodes[m].afCPU[m_nDataIndex] = atof( aNodes[n].strCPU)/10 ;
				bFound = TRUE ;
				break;
			}
		}
		if (!bFound)
			{
				NODE_DRAW nd ;
				
				nd.nStart = m_nDataIndex ;
				nd.afCPU[m_nDataIndex] = atof(aNodes[n].strCPU)/10;
				nd.strNodeIP = aNodes[n].strIP ;
				m_aNodes.Add(nd);
			}
		
	
	}

	if (aNodes.GetCount())
	{
		m_nDataIndex++;
		if (m_nDataIndex==DRAW_BUFF_LEN)
		{
			m_nDataIndex = 0 ;
		}
	}
	Invalidate(FALSE);
}


